<!DOCTYPE html>


  <html class="dark page-post">


<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="utf-8">
  
  <title>Vue学习总结(一) | Poetry&#39;s Blog</title>

  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  
    <meta name="keywords" content="Vue,">
  

  <meta name="description" content="一、介绍  Vue是一套构建用户界面的 渐进式框架。Vue 的核心库只关注视图层，并且非常容易学习，非常容易与其它库或已有项目整合。  二、Vue实例构造器  每个 Vue.js 应用都是通过构造函数 Vue 创建一个 Vue 的根实例 启动的  var vm = new Vue(&amp;#123;// 选项&amp;#125;)  在实例化 Vue 时，需要传入一个选项对象，它可以包含数据、模板、挂载元素、方">
<meta name="keywords" content="Vue">
<meta property="og:type" content="article">
<meta property="og:title" content="Vue学习总结(一)">
<meta property="og:url" content="http://blog.poetries.top/2017/03/19/vue-summary-1/index.html">
<meta property="og:site_name" content="Poetry&#39;s Blog">
<meta property="og:description" content="一、介绍  Vue是一套构建用户界面的 渐进式框架。Vue 的核心库只关注视图层，并且非常容易学习，非常容易与其它库或已有项目整合。  二、Vue实例构造器  每个 Vue.js 应用都是通过构造函数 Vue 创建一个 Vue 的根实例 启动的  var vm = new Vue(&amp;#123;// 选项&amp;#125;)  在实例化 Vue 时，需要传入一个选项对象，它可以包含数据、模板、挂载元素、方">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://poetries1.gitee.io/img-repo/2019/10/635.png">
<meta property="og:image" content="http://blog.poetries.top/2017/03/19/vue-summary-1/images/1489915053427.jpg">
<meta property="og:image" content="http://blog.poetries.top/2017/03/19/vue-summary-1/images/1489926033814.jpg">
<meta property="og:image" content="http://image.beekka.com/blog/2015/bg2015020105.png">
<meta property="og:image" content="http://image.beekka.com/blog/2015/bg2015020106.png">
<meta property="og:image" content="http://image.beekka.com/blog/2015/bg2015020107.png">
<meta property="og:image" content="http://image.beekka.com/blog/2015/bg2015020109.png">
<meta property="og:image" content="http://image.beekka.com/blog/2015/bg2015020110.png">
<meta property="og:updated_time" content="2020-08-15T04:25:31.942Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Vue学习总结(一)">
<meta name="twitter:description" content="一、介绍  Vue是一套构建用户界面的 渐进式框架。Vue 的核心库只关注视图层，并且非常容易学习，非常容易与其它库或已有项目整合。  二、Vue实例构造器  每个 Vue.js 应用都是通过构造函数 Vue 创建一个 Vue 的根实例 启动的  var vm = new Vue(&amp;#123;// 选项&amp;#125;)  在实例化 Vue 时，需要传入一个选项对象，它可以包含数据、模板、挂载元素、方">
<meta name="twitter:image" content="https://poetries1.gitee.io/img-repo/2019/10/635.png">

  

  
    <link rel="icon" href="/favicon.ico">
  

  <link href="/css/styles.css?v=c114cbeddx" rel="stylesheet">
<link href="/css/other.css?v=c114cbeddx" rel="stylesheet">


  
    <link rel="stylesheet" href="/css/personal-style.css">
  

  

  
  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "//hm.baidu.com/hm.js?40b1f89aa80f2527b3db779c6898c879";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>


  
  <script type="text/javascript">
	(function(){
	    var bp = document.createElement('script');
	    var curProtocol = window.location.protocol.split(':')[0];
	    if (curProtocol === 'https') {
	        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
	    }
	    else {
	        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
	    }
	    var s = document.getElementsByTagName("script")[0];
	    s.parentNode.insertBefore(bp, s);
	})();
  </script>



  
    <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <link rel="stylesheet" href="//cdn.bootcss.com/font-awesome/4.3.0/css/font-awesome.min.css">
  

  <!-- 聊天系统 -->
  
    
   <link type="text/css" rel="stylesheet" href="/renxi/default.css">
   <style>
      #modal {
        position: static !important;
      }
      .filter {
        width: 100%;
        height: 100%;
        position: absolute;
        top: 0;
        left: 0;
        background: #fe5757;
        animation: colorChange 30s ease-in-out infinite;
        animation-fill-mode: both;
        mix-blend-mode: overlay;
      }
  
      @keyframes colorChange {
        0%, 100% {
            opacity: 0;
        }
        50% {
            opacity: .9;
        }
      }
   </style>
</head>
</html>
<body>
  
  
    <span id="toolbox-mobile" class="toolbox-mobile">导航</span>
  

  <div class="post-header CENTER">
   
  <div class="toolbox">
    <a class="toolbox-entry" href="/">
      <span class="toolbox-entry-text">导航</span>
      <i class="icon-angle-down"></i>
      <i class="icon-home"></i>
    </a>
    <ul class="list-toolbox">
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/archives/"
            rel="noopener noreferrer"
            target="_self"
            >
            博客
          </a>
        </li>
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/categories/"
            rel="noopener noreferrer"
            target="_self"
            >
            分类
          </a>
        </li>
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/tags/"
            rel="noopener noreferrer"
            target="_self"
            >
            标签
          </a>
        </li>
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/search/"
            rel="noopener noreferrer"
            target="_self"
            >
            搜索
          </a>
        </li>
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/link/"
            rel="noopener noreferrer"
            target="_self"
            >
            友链
          </a>
        </li>
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/about/"
            rel="noopener noreferrer"
            target="_self"
            >
            关于
          </a>
        </li>
      
    </ul>
  </div>


</div>


  <div id="toc" class="toc-article">
    <strong class="toc-title">文章目录<i class="iconfont toc-title" style="display:inline-block;color:#87998d;width:20px;height:20px;">&#xf004b;</i></strong>
    <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#一、介绍"><span class="toc-text">一、介绍</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#二、Vue实例"><span class="toc-text">二、Vue实例</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#三、模板语法"><span class="toc-text">三、模板语法</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#插值"><span class="toc-text">插值</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#四、计算属性"><span class="toc-text">四、计算属性</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#五、Class与Style绑定"><span class="toc-text">五、Class与Style绑定</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Class-与-Style-绑定"><span class="toc-text">Class 与 Style 绑定</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#绑定-HTML-Class"><span class="toc-text">绑定 HTML Class</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#绑定内联样式"><span class="toc-text">绑定内联样式</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#六、条件渲染"><span class="toc-text">六、条件渲染</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#七、列表渲染"><span class="toc-text">七、列表渲染</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#八、事件处理器"><span class="toc-text">八、事件处理器</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#九、表单控制绑定"><span class="toc-text">九、表单控制绑定</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#十、组件"><span class="toc-text">十、组件</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#什么是组件？"><span class="toc-text">什么是组件？</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#使用组件"><span class="toc-text">使用组件</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Props"><span class="toc-text">Props</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#十一、附录"><span class="toc-text">十一、附录</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#附录一-MVC、MVP、MVVM模式对比"><span class="toc-text">附录一 MVC、MVP、MVVM模式对比</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#MVC"><span class="toc-text">MVC</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#什么是MVC"><span class="toc-text">什么是MVC</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#模型（数据保存）"><span class="toc-text">模型（数据保存）</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#视图（用户界面）"><span class="toc-text">视图（用户界面）</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#控制器（业务逻辑）"><span class="toc-text">控制器（业务逻辑）</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#总结一下："><span class="toc-text">总结一下：</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#互动模式"><span class="toc-text">互动模式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#MVP"><span class="toc-text">MVP</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#MVVM"><span class="toc-text">MVVM</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#附录二-vue与其他框架的对比"><span class="toc-text">附录二 vue与其他框架的对比</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#React"><span class="toc-text">React</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#angular1"><span class="toc-text">angular1</span></a></li></ol></li></ol></li></ol>
  </div>
  




<div class="content content-post CENTER">
   <!-- canvas 彩带 -->
<canvas id="evanyou" width="1302" height="678" style="position: fixed;width: 100%;height: 100%;top: 0;left:0;z-index:-1;"></canvas>

<article id="post-vue-summary-1" class="article article-type-post" itemprop="blogPost">
  <header class="article-header" style="position:relative;">
    <h1 class="post-title">Vue学习总结(一)</h1>

    <div class="article-meta">
      <span>
        <i class="icon-calendar"></i>
        <span>2017.03.19</span>
      </span>

      
        <span class="article-author">
          <i class="icon-user"></i>
          <span>Poetry</span>
        </span>
      

      
  <span class="article-category">
    <i class="icon-list"></i>
    <a class="article-category-link" href="/categories/Front-End/">Front-End</a>
  </span>



      

      
      <i class="fa fa-eye"></i> 
        <span id="busuanzi_container_page_pv">
           &nbsp热度 <span id="busuanzi_value_page_pv">
           <i class="fa fa-spinner fa-spin"></i></span>℃
        </span>
      
      
       
          <span class="post-count">
            <i class="fa fa-file-word-o"></i>&nbsp
            <span>字数统计 7.4k字</span>
          </span>

          <span class="post-count">
            <i class="fa fa-columns"></i>&nbsp
            <span>阅读时长 30分</span>
          </span>
      
      
    </div>

    <i class="iconfont" id="toc-eye" style="display:inline-block;color:#b36619;position:absolute;top:0;right:0;cursor:pointer;
    font-size: 24px;">&#xe61c;</i>

  </header>

  <div class="article-content">
    
      <div id="container">
        <h2 id="一、介绍"><a href="#一、介绍" class="headerlink" title="一、介绍"></a>一、介绍</h2><p><img src="https://poetries1.gitee.io/img-repo/2019/10/635.png" alt></p>
<ul>
<li><code>Vue</code>是一套构建用户界面的 渐进式框架。<code>Vue</code> 的核心库只关注视图层，并且非常容易学习，非常容易与其它库或已有项目整合。</li>
</ul>
<h2 id="二、Vue实例"><a href="#二、Vue实例" class="headerlink" title="二、Vue实例"></a>二、Vue实例</h2><p><strong>构造器</strong></p>
<ul>
<li>每个 <code>Vue.js</code> 应用都是通过构造函数 <code>Vue</code> 创建一个 <code>Vue</code> 的根实例 启动的</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123;</span><br><span class="line"><span class="comment">// 选项</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<ul>
<li>在实例化 <code>Vue</code> 时，需要传入一个选项对象，它可以包含数据、模板、挂载元素、方法、生命周期钩子等选项。全部的选项可以在 <code>API</code> 文档中查看</li>
</ul>
<p><strong>属性与方法</strong></p>
<ul>
<li>每个 <code>Vue</code>实例都会代理其<code>data</code> 对象里所有的属性</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> data = &#123; <span class="attr">a</span>: <span class="number">1</span> &#125;</span><br><span class="line"><span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123;</span><br><span class="line">data: data</span><br><span class="line">&#125;)</span><br><span class="line">vm.a === data.a</span><br><span class="line"><span class="comment">// -&gt; true</span></span><br><span class="line"><span class="comment">// 设置属性也会影响到原始数据</span></span><br><span class="line">vm.a = <span class="number">2</span></span><br><span class="line">data.a <span class="comment">// -&gt; 2</span></span><br><span class="line"><span class="comment">// ... 反之亦然</span></span><br><span class="line">data.a = <span class="number">3</span></span><br><span class="line">vm.a <span class="comment">// -&gt; 3</span></span><br></pre></td></tr></table></figure>
<ul>
<li>除了 <code>data</code>属性， <code>Vue</code>实例暴露了一些有用的实例属性与方法。这些属性与方法都有前缀 <code>$</code>，以便与代理的<code>data</code>属性区分。例如：</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> data = &#123; <span class="attr">a</span>: <span class="number">1</span> &#125;</span><br><span class="line"><span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123;</span><br><span class="line">el: <span class="string">'#example'</span>,</span><br><span class="line">data: data</span><br><span class="line">&#125;)</span><br><span class="line">vm.$data === data</span><br><span class="line"><span class="comment">// -&gt; true</span></span><br><span class="line">vm.$el === <span class="built_in">document</span>.getElementById(<span class="string">'example'</span>)</span><br><span class="line"><span class="comment">// -&gt; true</span></span><br><span class="line"><span class="comment">// $watch 是一个实例方法</span></span><br><span class="line">vm.$watch(<span class="string">'a'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">newVal, oldVal</span>) </span>&#123;</span><br><span class="line"><span class="comment">// 这个回调将在 `vm.a` 改变后调用</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<p><strong>实例生命周期</strong></p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123;</span><br><span class="line">data: &#123; <span class="attr">a</span>: <span class="number">1</span> &#125;,</span><br><span class="line">created: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="comment">// `this` 指向 vm 实例</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">'a is: '</span> + <span class="keyword">this</span>.a)</span><br><span class="line">&#125;</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// -&gt; "a is: 1"</span></span><br></pre></td></tr></table></figure>
<ul>
<li>也有一些其它的钩子，在实例生命周期的不同阶段调用，如 <code>mounted</code> 、 <code>updated</code> 、 <code>destroyed</code> 。钩子的 <code>this</code> 指向调用它的 <code>Vue</code> 实例。一些用户可能会问 <code>Vue.js</code> 是否有“控制器”的概念？答案是，没有。组件的自定义逻辑可以分布在这些钩子中</li>
</ul>
<p><strong>生命周期图示</strong></p>
<p><img src="./images/1489915053427.jpg" alt="生命周期图示" title="1489915053427"></p>
<h2 id="三、模板语法"><a href="#三、模板语法" class="headerlink" title="三、模板语法"></a>三、模板语法</h2><ul>
<li><p><code>Vue.js</code> 使用了基于 <code>HTML</code> 的模版语法，允许开发者声明式地将 <code>DOM</code> 绑定至底层 <code>Vue</code> 实例的数据。所有<code>Vue.js</code> 的模板都是合法的 <code>HTML</code> ，所以能被遵循规范的浏览器和 <code>HTML</code> 解析器解析。</p>
</li>
<li><p>在底层的实现上， <code>Vue</code>将模板编译成虚拟<code>DOM</code> 渲染函数。结合响应系统，在应用状态改变时， <code>Vue</code> 能够智能地计算出重新渲染组件的最小代价并应用到 <code>DOM</code> 操作上。</p>
</li>
</ul>
<h3 id="插值"><a href="#插值" class="headerlink" title="插值"></a>插值</h3><p><strong>文本</strong></p>
<ul>
<li>数据绑定最常见的形式就是使用 “Mustache” 语法（双大括号）的文本插值</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">span</span>&gt;</span>Message: &#123;&#123; msg &#125;&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li><code>Mustache</code> 标签将会被替代为对应数据对象上 <code>msg</code> 属性的值。无论何时，绑定的数据对象上 <code>msg</code> 属性发生了改变，插值处的内容都会更新</li>
<li>通过使用 <code>v-once</code> 指令，你也能执行一次性地插值，当数据改变时，插值处的内容不会更新。但请留心这会影响到该节点上所有的数据绑定</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">v-once</span>&gt;</span>This will never change: &#123;&#123; msg &#125;&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>纯 HTML</strong></p>
<ul>
<li>双大括号会将数据解释为纯文本，而非 <code>HTML</code> 。为了输出真正的 <code>HTML</code>，你需要使用<code>v-html</code>指令：</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-html</span>=<span class="string">"rawHtml"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>被插入的内容都会被当做 <code>HTML</code> —— 数据绑定会被忽略</li>
<li>你的站点上动态渲染的任意 <code>HTML</code> 可能会非常危险，因为它很容易导致 <code>XSS</code> 攻击。请只对可信内容使用<code>HTML</code> 插值，绝不要对用户提供的内容插值</li>
</ul>
<p><strong>属性</strong></p>
<ul>
<li>Mustache 不能在 <code>HTML</code> 属性中使用，应使用 <code>v-bind</code> 指令：</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-bind:id</span>=<span class="string">"dynamicId"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>使用 JavaScript 表达式</strong></p>
<ul>
<li>对于所有的数据绑定， <code>Vue.js</code>都提供了完全的 <code>JavaScript</code>表达式支持。</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line">&#123;&#123; number + 1 &#125;&#125;&#123;&#123; ok ? 'YES' : 'NO' &#125;&#125;</span><br><span class="line">&#123;&#123; message.split('').reverse().join('') &#125;&#125;</span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-bind:id</span>=<span class="string">"'list-' + id"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>这些表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被解析</li>
</ul>
<p><strong>过滤器</strong></p>
<ul>
<li><code>Vue.js</code> 允许你自定义过滤器，被用作一些常见的文本格式化。过滤器应该被添加在<code>mustache</code> 插值的尾部，由“管道符”指示：</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">&#123;&#123; message | capitalize &#125;&#125;</span><br></pre></td></tr></table></figure>
<p><strong>指令</strong></p>
<ul>
<li>指令（<code>Directives</code>）是带有<code>v-</code>前缀的特殊属性。指令属性的值预期是单一 <code>JavaScript</code>表达式（除了<code>v-for</code> ，之后再讨论）</li>
<li>指令的职责就是当其表达式的值改变时相应地将某些行为应用到 DOM 上</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">v-if</span>=<span class="string">"seen"</span>&gt;</span>Now you see me<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>这里， <code>v-if</code> 指令将根据表达式 seen 的值的真假来移除/插入<code>&lt;p&gt;</code>元素</li>
</ul>
<p><strong>参数</strong></p>
<ul>
<li>一些指令能接受一个“参数”，在指令后以冒号指明。例如，<code>v-bind</code>指令被用来响应地更新 <code>HTML</code> 属性</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">v-bind:href</span>=<span class="string">"url"</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li><p>在这里 <code>href</code>是参数，告知<code>v-bind</code> 指令将该元素的 <code>href</code> 属性与表达式 <code>url</code>的值绑定</p>
</li>
<li><p>另一个例子是 <code>v-on</code> 指令，它用于监听 <code>DOM</code> 事件：</p>
</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">v-on:click</span>=<span class="string">"doSomething"</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>修饰符</strong></p>
<ul>
<li>修饰符（Modifiers）是以半角句号<code>.</code>指明的特殊后缀，用于指出一个指令应该以特殊方式绑定</li>
<li>例如，<code>.prevent</code> 修饰符告诉 <code>v-on</code> 指令对于触发的事件调用 <code>event.preventDefault()</code></li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">v-on:submit.prevent</span>=<span class="string">"onSubmit"</span>&gt;</span><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>缩写</strong></p>
<ul>
<li><code>v-</code> 前缀在模板中是作为一个标示 <code>Vue</code> 特殊属性的明显标识</li>
<li><p><code>Vue.js</code> 为两个最为常用的指令提供了特别的缩写</p>
</li>
<li><p><code>v-bind</code> 缩写</p>
</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 完整语法 --&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">v-bind:href</span>=<span class="string">"url"</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 缩写 --&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">:href</span>=<span class="string">"url"</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li><code>v-on</code> 缩写</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 完整语法 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">v-on:click</span>=<span class="string">"doSomething"</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 缩写 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> @<span class="attr">click</span>=<span class="string">"doSomething"</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h2 id="四、计算属性"><a href="#四、计算属性" class="headerlink" title="四、计算属性"></a>四、计算属性</h2><ul>
<li>在模板中绑定表达式是非常便利的，但是它们实际上只用于简单的操作。在模板中放入太多的逻辑会让模板过重且难以维护。例如：</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"example"</span>&gt;</span> &#123;&#123; message.split('').reverse().join('') &#125;&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>在这种情况下，模板不再简单和清晰。在实现反向显示 <code>message</code> 之前，你应该确认它。这个问题在你不止一次反向显示 <code>message</code> 的时候变得更加糟糕。</li>
<li>这就是为什么任何复杂逻辑，你都应当使用计算属性</li>
</ul>
<p><strong>基础例子</strong></p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"example"</span>&gt;</span> </span><br><span class="line">   <span class="tag">&lt;<span class="name">p</span>&gt;</span>Original message: "&#123;&#123; message &#125;&#125;"<span class="tag">&lt;/<span class="name">p</span>&gt;</span> </span><br><span class="line">   <span class="tag">&lt;<span class="name">p</span>&gt;</span>Computed reversed message: "&#123;&#123; reversedMessage &#125;&#125;"<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123; </span><br><span class="line">	el: <span class="string">'#example'</span>, <span class="attr">data</span>: &#123; <span class="attr">message</span>: <span class="string">'Hello'</span> &#125;, </span><br><span class="line">	computed: &#123;</span><br><span class="line">	  <span class="comment">//a computed getter </span></span><br><span class="line">	reversedMessage: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; </span><br><span class="line">	  <span class="comment">// `this` points to the vm instance </span></span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">this</span>.message.split(<span class="string">''</span>).reverse().join(<span class="string">''</span>)</span><br><span class="line">&#125; &#125;&#125;)</span><br></pre></td></tr></table></figure>
<ul>
<li><p>结果：</p>
<ul>
<li>Original message: “Hello”</li>
<li>Computed reversed message: “olleH”</li>
</ul>
</li>
<li><p>这里我们声明了一个计算属性 <code>reversedMessage</code> 。我们提供的函数将用作属性</p>
</li>
</ul>
<p><strong>计算缓存 vs Methods</strong></p>
<ul>
<li>你可能已经注意到我们可以通过调用表达式中的<code>method</code>来达到同样的效果：</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>Reversed message: "&#123;&#123; reverseMessage() &#125;&#125;"<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// in component</span></span><br><span class="line">methods: &#123;</span><br><span class="line">reverseMessage: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">this</span>.message.split(<span class="string">'</span></span><br><span class="line"><span class="string">	'</span>).reverse().join(<span class="string">''</span>) </span><br><span class="line">&#125;&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li><p>不经过计算属性，我们可以在 <code>method</code> 中定义一个相同的函数来替代它。对于最终的结果，两种方式确实是相同的。然而，不同的是计算属性是基于它的依赖缓存。计算属性只有在它的相关依赖发生改变时才会重新<br>取值。这就意味着只要 <code>message</code> 没有发生改变，多次访问<code>reversedMessage</code> 计算属性会立即返回之前的计算结果，而不必再次执行函数。</p>
</li>
<li><p>这也同样意味着如下计算属性将不会更新，因为 <code>Date.now()</code>不是响应式依赖：</p>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">computed: &#123; <span class="attr">now</span>: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; <span class="keyword">return</span> <span class="built_in">Date</span>.now() &#125;&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li><p>相比而言，每当重新渲染的时候，<code>method</code> 调用总会执行函数</p>
</li>
<li><p>我们为什么需要缓存？假设我们有一个重要的计算属性 <code>A</code> ，这个计算属性需要一个巨大的数组遍历和做大量的计算。然后我们可能有其他的计算属性依赖于 <code>A</code> 。如果没有缓存，我们将不可避免的多次执行 <code>A</code> 的 <code>getter</code>！如果你不希望有缓存，请用 <code>method</code> 替代</p>
</li>
</ul>
<p><strong>计算属性 vs Watched Property</strong></p>
<ul>
<li><code>Vue.js</code> 提供了一个方法<code>$watch</code> ，它用于观察 <code>Vue</code>实例上的数据变动</li>
</ul>
<p><strong>计算 setter</strong></p>
<ul>
<li>计算属性默认只有 <code>getter</code>，不过在需要时你也可以提供一个 <code>setter</code>：</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// ...</span></span><br><span class="line">computed: &#123;</span><br><span class="line">fullName: &#123; </span><br><span class="line">   <span class="comment">// getter </span></span><br><span class="line">	<span class="keyword">get</span>: function () &#123; </span><br><span class="line">		<span class="keyword">return</span> <span class="keyword">this</span>.firstName + <span class="string">' '</span> + <span class="keyword">this</span>.lastName </span><br><span class="line">	&#125;, </span><br><span class="line">	<span class="comment">// setter </span></span><br><span class="line">	<span class="keyword">set</span>: function (newValue) &#123;</span><br><span class="line">		<span class="keyword">var</span> names = newValue.split(<span class="string">' '</span>) </span><br><span class="line">		<span class="keyword">this</span>.firstName = names[<span class="number">0</span>] </span><br><span class="line">		<span class="keyword">this</span>.lastName = names[names.length - <span class="number">1</span>] </span><br><span class="line"></span><br><span class="line">	&#125;</span><br><span class="line">&#125;&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>现在在运行<code>vm.fullName = &#39;John Doe&#39;</code> 时， <code>setter</code>会被调用， <code>vm.firstName</code> 和<code>vm.lastName</code> 也会被对应更新</li>
</ul>
<p><strong>观察 Watchers</strong></p>
<ul>
<li>虽然计算属性在大多数情况下更合适，但有时也需要一个自定义的 <code>watcher</code> 。这是为什么 <code>Vue</code> 提供一个更通用的方法通过 <code>watch</code> 选项，来响应数据的变化。当你想要在数据变化响应时，执行异步操作或昂贵操作时，这是很有用的</li>
</ul>
<h2 id="五、Class与Style绑定"><a href="#五、Class与Style绑定" class="headerlink" title="五、Class与Style绑定"></a>五、Class与Style绑定</h2><h3 id="Class-与-Style-绑定"><a href="#Class-与-Style-绑定" class="headerlink" title="Class 与 Style 绑定"></a>Class 与 Style 绑定</h3><ul>
<li>数据绑定一个常见需求是操作元素的 <code>class</code> 列表和它的内联样式。因为它们都是属性 ，我们可以用 <code>v-bind</code>处理它们：只需要计算出表达式最终的字符串。不过，字符串拼接麻烦又易错。因此，在 <code>v-bind</code> 用于<code>class</code> 和 <code>style</code>时， <code>Vue.js</code> 专门增强了它。表达式的结果类型除了字符串之外，还可以是对象或数组</li>
</ul>
<h3 id="绑定-HTML-Class"><a href="#绑定-HTML-Class" class="headerlink" title="绑定 HTML Class"></a>绑定 HTML Class</h3><p><strong>对象语法</strong></p>
<ul>
<li>我们可以传给<code>v-bind:class</code> 一个对象，以动态地切换 <code>class</code></li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-bind:class</span>=<span class="string">"&#123; active: isActive &#125;"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>上面的语法表示<code>class active</code>的更新将取决于数据属性<code>isActive</code> 是否为真值</li>
<li>我们也可以在对象中传入更多属性用来动态切换多个<code>class</code>。此外， v-<code>bind:class</code> 指令可以与普通的<code>class</code> 属性共存。如下模板:</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"static"</span> <span class="attr">v-bind:class</span>=<span class="string">"&#123; active: isActive, 'text-danger': hasError &#125;"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>如下 <code>data</code>:</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">data: &#123; <span class="attr">isActive</span>: <span class="literal">true</span>, <span class="attr">hasError</span>: <span class="literal">false</span>&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>渲染为:</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"static active"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li><p>当 <code>isActive</code> 或者 <code>hasError</code> 变化时，<code>class</code> 列表将相应地更新。例如，如果 <code>hasError</code>的值为<code>true</code> ， <code>class</code>列表将变为<code>&quot;static active text-danger&quot;</code></p>
</li>
<li><p>你也可以直接绑定数据里的一个对象</p>
</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-bind:class</span>=<span class="string">"classObject"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">data: &#123; <span class="attr">classObject</span>: &#123; <span class="attr">active</span>: <span class="literal">true</span>, <span class="string">'text-danger'</span>: <span class="literal">false</span> &#125;&#125;</span><br></pre></td></tr></table></figure>
<p><strong>数组语法</strong></p>
<ul>
<li>我们可以把一个数组传给 <code>v-bind:class</code> ，以应用一个 <code>class</code> 列表</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-bind:class</span>=<span class="string">"[activeClass, errorClass]"</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">data: &#123; <span class="attr">activeClass</span>: <span class="string">'active'</span>, <span class="attr">errorClass</span>: <span class="string">'text-danger'</span>&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>渲染为:</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"active text-danger"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>如果你也想根据条件切换列表中的 <code>class</code> ，可以用三元表达式</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-bind:class</span>=<span class="string">"[isActive ? activeClass : '', errorClass]"</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h3 id="绑定内联样式"><a href="#绑定内联样式" class="headerlink" title="绑定内联样式"></a>绑定内联样式</h3><p><strong>对象语法</strong></p>
<ul>
<li><code>v-bind:style</code> 的对象语法十分直观——看着非常像<code>CSS</code> ，其实它是一个 <code>JavaScript</code> 对象。 <code>CSS</code> 属性名可以用驼峰式（camelCase）或短横分隔命名（kebab-case）</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> </span></span><br><span class="line"><span class="tag"><span class="attr">v-bind:style</span>=<span class="string">"&#123; color: activeColor, fontSize: fontSize + 'px' &#125;"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">data: &#123; <span class="attr">activeColor</span>: <span class="string">'red'</span>, <span class="attr">fontSize</span>: <span class="number">30</span>&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>直接绑定到一个样式对象通常更好，让模板更清晰</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-bind:style</span>=<span class="string">"styleObject"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">data: &#123; <span class="attr">styleObject</span>: &#123; <span class="attr">color</span>: <span class="string">'red'</span>, <span class="attr">fontSize</span>: <span class="string">'13px'</span> &#125;&#125;</span><br></pre></td></tr></table></figure>
<p><strong>数组语法</strong></p>
<ul>
<li><code>v-bind:style</code> 的数组语法可以将多个样式对象应用到一个元素上</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-bind:style</span>=<span class="string">"[baseStyles, overridingStyles]"</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>自动添加前缀</strong></p>
<ul>
<li>当 <code>v-bind:style</code> 使用需要特定前缀的 <code>CSS</code> 属性时，如 <code>transform</code> ，<code>Vue.js</code>会自动侦测并添加相应的前缀</li>
</ul>
<h2 id="六、条件渲染"><a href="#六、条件渲染" class="headerlink" title="六、条件渲染"></a>六、条件渲染</h2><p><strong>v-if</strong></p>
<ul>
<li>在字符串模板中，如 <code>Handlebars</code>，我们得像这样写一个条件块</li>
</ul>
<figure class="highlight"><table><tr><td class="code"><pre><span class="line">&lt;!-- Handlebars 模板 --&gt;</span><br><span class="line">&#123;&#123;#if ok&#125;&#125; &lt;h1&gt;Yes&lt;/h1&gt;&#123;&#123;/if&#125;&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>在 <code>Vue.js</code>，我们使用 <code>v-if</code>指令实现同样的功能</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">h1</span> <span class="attr">v-if</span>=<span class="string">"ok"</span>&gt;</span>Yes<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>也可以用 <code>v-else</code>添加一个 <code>“else”</code>块</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">h1</span> <span class="attr">v-if</span>=<span class="string">"ok"</span>&gt;</span>Yes<span class="tag">&lt;/<span class="name">h1</span>&gt;</span><span class="tag">&lt;<span class="name">h1</span> <span class="attr">v-else</span>&gt;</span>No<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>template v-if</strong></p>
<ul>
<li>因为 <code>v-if</code> 是一个指令，需要将它添加到一个元素上。但是如果我们想切换多个元素呢？此时我们可以把一个 <code>&lt;template&gt;</code> 元素当做包装元素，并在上面使用 <code>v-if</code> ，最终的渲染结果不会包含它</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span> <span class="attr">v-if</span>=<span class="string">"ok"</span>&gt;</span> <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Title<span class="tag">&lt;/<span class="name">h1</span>&gt;</span> <span class="tag">&lt;<span class="name">p</span>&gt;</span>Paragraph 1<span class="tag">&lt;/<span class="name">p</span>&gt;</span> <span class="tag">&lt;<span class="name">p</span>&gt;</span>Paragraph 2<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>v-else</strong></p>
<ul>
<li><p>可以用 <code>v-else</code>指令给 <code>v-if</code>或 <code>v-show</code> 添加一个 <code>“else”</code> 块</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-if</span>=<span class="string">"Math.random() &gt; 0.5"</span>&gt;</span> Sorry<span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-else</span>&gt;</span> Not sorry<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p><code>v-else</code> 元素必须紧跟在<code>v-if</code>或 <code>v-show</code> 元素的后面——否则它不能被识别</p>
</li>
</ul>
<p><strong>v-show</strong></p>
<ul>
<li>另一个根据条件展示元素的选项是<code>v-show</code>指令。用法大体上一样</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">h1</span> <span class="attr">v-show</span>=<span class="string">"ok"</span>&gt;</span>Hello!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li><p>不同的是有 <code>v-show</code> 的元素会始终渲染并保持在 <code>DOM</code> 中。 <code>v-show</code>是简单的切换元素的 <code>CSS</code> 属性<code>display</code></p>
</li>
<li><p>注意 <code>v-show</code> 不支持 <code>&lt;template&gt;</code> 语法</p>
</li>
</ul>
<p><strong>v-if vs. v-show</strong></p>
<ul>
<li><code>v-if</code> 是真实的条件渲染，因为它会确保条件块在切换当中适当地销毁与重建条件块内的事件监听器和子组件</li>
<li><code>v-if</code>也是惰性的：如果在初始渲染时条件为假，则什么也不做</li>
<li>相比之下， <code>v-show</code> 简单得多——元素始终被编译并保留，只是简单地基于 <code>CSS</code> 切换</li>
<li>一般来说， <code>v-if</code>有更高的切换消耗而 <code>v-show</code> 有更高的初始渲染消耗</li>
<li>因此，如果需要频繁切换使用<code>v-show</code>较好，如果在运行时条件不大可能改变则使用<code>v-if</code>较好</li>
</ul>
<h2 id="七、列表渲染"><a href="#七、列表渲染" class="headerlink" title="七、列表渲染"></a>七、列表渲染</h2><p><strong>v-for</strong></p>
<ul>
<li>我们用 <code>v-for</code>指令根据一组数组的选项列表进行渲染。<code>v-for</code>指令需要以 <code>item in items</code> 形式的特殊语法， <code>items</code> 是源数据数组并且 <code>item</code> 是数组元素迭代的别名</li>
<li>在 <code>v-for</code> 块中，我们拥有对父作用域属性的完全访问权限。 <code>v-for</code> 还支持一个可选的第二个参数为当前项的索引</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ul</span> <span class="attr">id</span>=<span class="string">"example-2"</span>&gt;</span> </span><br><span class="line">	<span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">"(item, index) in items"</span>&gt;</span> </span><br><span class="line">		&#123;&#123; parentMessage &#125;&#125; - &#123;&#123; index &#125;&#125; - &#123;&#123; item.message &#125;&#125; </span><br><span class="line">	<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>你也可以用 <code>of</code>替代 <code>in</code>作为分隔符，因为它是最接近 <code>JavaScript</code> 迭代器的语法</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-for</span>=<span class="string">"item of items"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>Template v-for</strong></p>
<ul>
<li>如同 <code>v-if</code>模板，你也可以用带有 <code>v-for</code> 的 <code>&lt;template&gt;</code>标签来渲染多个元素块。例如：<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ul</span>&gt;</span> </span><br><span class="line">	<span class="tag">&lt;<span class="name">template</span> <span class="attr">v-for</span>=<span class="string">"item in items"</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">li</span>&gt;</span>&#123;&#123; item.msg &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span> </span><br><span class="line">		<span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">"divider"</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span> </span><br><span class="line">	<span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<p><strong>对象迭代 v-for</strong></p>
<ul>
<li>你也可以用<code>v-for</code> 通过一个对象的属性来迭代</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ul</span> <span class="attr">id</span>=<span class="string">"repeat-object"</span> <span class="attr">class</span>=<span class="string">"demo"</span>&gt;</span> </span><br><span class="line">	<span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">"value in object"</span>&gt;</span> &#123;&#123; value &#125;&#125; <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">new</span> Vue(&#123;</span><br><span class="line">	el: <span class="string">'#repeat-object'</span>, </span><br><span class="line">	data: &#123; </span><br><span class="line">		object: &#123;</span><br><span class="line">			FirstName: <span class="string">'John'</span>, </span><br><span class="line">			LastName: <span class="string">'Doe'</span>, <span class="attr">Age</span>: <span class="number">30</span></span><br><span class="line">	&#125; </span><br><span class="line">&#125;&#125;)</span><br></pre></td></tr></table></figure>
<ul>
<li><p>你也可以提供第二个的参数为键名</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-for</span>=<span class="string">"(value, key) in object"</span>&gt;</span> &#123;&#123; key &#125;&#125; : &#123;&#123; value &#125;&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>第三个参数为索引</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-for</span>=<span class="string">"(value, key, index) in object"</span>&gt;</span></span><br><span class="line">	&#123;&#123; index &#125;&#125;. &#123;&#123; key &#125;&#125; : &#123;&#123; value &#125;&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<p><strong>整数迭代 v-for</strong></p>
<ul>
<li><code>v-for</code> 也可以取整数。在这种情况下，它将重复多次模板</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span> </span><br><span class="line">	<span class="tag">&lt;<span class="name">span</span> <span class="attr">v-for</span>=<span class="string">"n in 10"</span>&gt;</span>&#123;&#123; n &#125;&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>结果： 1 2 3 4 5 6 7 8 9 10</li>
</ul>
<p><strong>组件 和 v-for</strong></p>
<ul>
<li><p>在自定义组件里，你可以像任何普通元素一样用 <code>v-for</code></p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">my-component</span> <span class="attr">v-for</span>=<span class="string">"item in items"</span>&gt;</span><span class="tag">&lt;/<span class="name">my-component</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>然而他不能自动传递数据到组件里，因为组件有自己独立的作用域。为了传递迭代数据到组件里，我们要用<code>props</code></p>
</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">my-component</span> <span class="attr">v-for</span>=<span class="string">"(item, index) in items"</span> </span></span><br><span class="line"><span class="tag"><span class="attr">v-bind:item</span>=<span class="string">"item"</span> <span class="attr">v-bind:index</span>=<span class="string">"index"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">my-component</span>&gt;</span>&gt;</span><br></pre></td></tr></table></figure>
<ul>
<li>不自动注入 <code>item</code>到组件里的原因是，因为这使得组件会紧密耦合到 <code>v-for</code>如何运作。在一些情况下，明确数据的来源可以使组件可重用。</li>
</ul>
<h2 id="八、事件处理器"><a href="#八、事件处理器" class="headerlink" title="八、事件处理器"></a>八、事件处理器</h2><p><strong>监听事件</strong></p>
<ul>
<li>可以用 <code>v-on</code> 指令监听 <code>DOM</code> 事件来触发一些 <code>JavaScript</code> 代码</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"example-1"</span>&gt;</span> </span><br><span class="line">	<span class="tag">&lt;<span class="name">button</span> <span class="attr">v-on:click</span>=<span class="string">"counter += 1"</span>&gt;</span>增加 1<span class="tag">&lt;/<span class="name">button</span>&gt;</span> </span><br><span class="line">	<span class="tag">&lt;<span class="name">p</span>&gt;</span>这个按钮被点击了 &#123;&#123; counter &#125;&#125; 次。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> example1 = <span class="keyword">new</span> Vue(&#123; </span><br><span class="line">el: <span class="string">'#example-1'</span>, </span><br><span class="line">data: &#123; </span><br><span class="line">	counter: <span class="number">0</span> </span><br><span class="line">&#125;&#125;)</span><br></pre></td></tr></table></figure>
<p><strong>方法事件处理器</strong></p>
<ul>
<li>许多事件处理的逻辑都很复杂，所以直接把 <code>JavaScript</code> 代码写在 <code>v-on</code> 指令中是不可行的。因此 <code>v-on</code> 可以接收一个定义的方法来调用</li>
</ul>
<p><strong>内联处理器方法</strong></p>
<ul>
<li>除了直接绑定到一个方法，也可以用内联 <code>JavaScript</code>语句</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"example-3"</span>&gt;</span> </span><br><span class="line">	<span class="tag">&lt;<span class="name">button</span> <span class="attr">v-on:click</span>=<span class="string">"say('hi')"</span>&gt;</span>Say hi<span class="tag">&lt;/<span class="name">button</span>&gt;</span> </span><br><span class="line">	<span class="tag">&lt;<span class="name">button</span> <span class="attr">v-on:click</span>=<span class="string">"say('what')"</span>&gt;</span>Say what<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">new</span> Vue(&#123;</span><br><span class="line">el: <span class="string">'#example-3'</span>, </span><br><span class="line">methods: &#123; </span><br><span class="line">	say: <span class="function"><span class="keyword">function</span> (<span class="params">message</span>) </span>&#123; </span><br><span class="line">		alert(message) </span><br><span class="line">	&#125;</span><br><span class="line">&#125;&#125;)</span><br></pre></td></tr></table></figure>
<ul>
<li>有时也需要在内联语句处理器中访问原生 <code>DOM</code> 事件。可以用特殊变量 <code>$event</code>把它传入方法</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">button</span> </span></span><br><span class="line"><span class="tag"><span class="attr">v-on:click</span>=<span class="string">"warn('Form cannot be submitted yet.', $event)"</span>&gt;</span></span><br><span class="line">Submit<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">methods: &#123;</span><br><span class="line">warn: <span class="function"><span class="keyword">function</span> (<span class="params">message, event</span>) </span>&#123;</span><br><span class="line"><span class="comment">// 现在我们可以访问原生事件对象 </span></span><br><span class="line">		<span class="keyword">if</span>(event) &#123;</span><br><span class="line">			event.preventDefault() </span><br><span class="line">			alert(message) </span><br><span class="line">		&#125;</span><br><span class="line">&#125;&#125;</span><br></pre></td></tr></table></figure>
<p><strong>事件修饰符</strong></p>
<ul>
<li>在事件处理程序中调用<code>event.preventDefault()</code>或<code>event.stopPropagation()</code>是非常常见的需求。尽管我们可以在<code>methods</code> 中轻松实现这点，但更好的方式是：<code>methods</code> 只有纯粹的数据逻辑，而不是去处理<code>DOM</code> 事件细节</li>
<li>为了解决这个问题， <code>Vue.js</code> 为 <code>v-on</code>提供了 事件修饰符。通过由点(<code>.</code>)表示的指令后缀来调用修饰符</li>
<li><code>.stop</code></li>
<li><code>.prevent</code></li>
<li><code>.capture</code></li>
<li><code>.self</code></li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 阻止单击事件冒泡 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">v-on:click.stop</span>=<span class="string">"doThis"</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 提交事件不再重载页面 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">v-on:submit.prevent</span>=<span class="string">"onSubmit"</span>&gt;</span><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 修饰符可以串联 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">v-on:click.stop.prevent</span>=<span class="string">"doThat"</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 只有修饰符 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">v-on:submit.prevent</span>&gt;</span><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 添加事件侦听器时使用时间捕获模式 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-on:click.capture</span>=<span class="string">"doThis"</span>&gt;</span>...<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 只当事件在该元素本身（而不是子元素）触发时触发回调 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">v-on:click.self</span>=<span class="string">"doThat"</span>&gt;</span>...<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>按键修饰符</strong></p>
<ul>
<li>在监听键盘事件时，我们经常需要监测常见的键值。 <code>Vue</code>允许为 <code>v-on</code>在监听键盘事件时添加按键修饰符：</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 只有在 keyCode 是 13 时调用 vm.submit() --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">v-on:keyup.13</span>=<span class="string">"submit"</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li><p>记住所有的 <code>keyCode</code>比较困难，所以 <code>Vue</code>为最常用的按键提供了别名</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 同上 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">v-on:keyup.enter</span>=<span class="string">"submit"</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 缩写语法 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> @<span class="attr">keyup.enter</span>=<span class="string">"submit"</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>全部的按键别名：</p>
<ul>
<li><code>enter</code></li>
<li><code>tab</code></li>
<li><code>delete</code> (捕获 “删除” 和 “退格” 键)</li>
<li><code>esc</code></li>
<li><code>space</code></li>
<li><code>up</code></li>
<li><code>down</code></li>
<li><code>left</code></li>
<li><code>right</code></li>
</ul>
</li>
</ul>
<p><strong>为什么在 HTML 中监听事件?</strong></p>
<ul>
<li><p>你可能注意到这种事件监听的方式违背了关注点分离（separation of concern）传统理念。不必担心，因为所有的 <code>Vue.js</code>事件处理方法和表达式都严格绑定在当前视图的 <code>ViewModel</code>上，它不会导致任何维护上的困难。</p>
</li>
<li><p>实际上，使用 <code>v-on</code>有几个好处</p>
<ul>
<li>扫一眼<code>HTML</code> 模板便能轻松定位在 <code>JavaScript</code>代码里对应的方法</li>
<li>因为你无须在 <code>JavaScript</code>里手动绑定事件，你的 <code>ViewModel</code>代码可以是非常纯粹的逻辑，和 <code>DOM</code> 完全解耦，更易于测试。</li>
<li>当一个 <code>ViewModel</code>被销毁时，所有的事件处理器都会自动被删除。你无须担心如何自己清理它们。</li>
</ul>
</li>
</ul>
<h2 id="九、表单控制绑定"><a href="#九、表单控制绑定" class="headerlink" title="九、表单控制绑定"></a>九、表单控制绑定</h2><p><strong>基础用法</strong></p>
<ul>
<li>你可以用 <code>v-model</code>指令在表单控件元素上创建双向数据绑定</li>
<li>它会根据控件类型自动选取正确的方法来更新元素。</li>
<li>尽管有些神奇，但 <code>v-model</code>本质上不过是语法糖，它负责监听用户的输入事件以更新数据，并特别处理一些极端的例子。</li>
<li><code>v-model</code> 并不关心表单控件初始化所生成的值。因为它会选择<code>Vue</code>实例数据来作为具体的值。</li>
</ul>
<p><strong>文本</strong></p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">v-model</span>=<span class="string">"message"</span> <span class="attr">placeholder</span>=<span class="string">"edit me"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>Message is: &#123;&#123; message &#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>复选框</strong></p>
<ul>
<li>单个勾选框，逻辑值</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">id</span>=<span class="string">"checkbox"</span> <span class="attr">v-model</span>=<span class="string">"checked"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">label</span> <span class="attr">for</span>=<span class="string">"checkbox"</span>&gt;</span>&#123;&#123; checked&#125;&#125;<span class="tag">&lt;/<span class="name">label</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>多个勾选框，绑定到同一个数组</li>
</ul>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">id</span>=<span class="string">"jack"</span> <span class="attr">value</span>=<span class="string">"Jack"</span> <span class="attr">v-model</span>=<span class="string">"checkedNames"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">label</span> <span class="attr">for</span>=<span class="string">"jack"</span>&gt;</span>Jack<span class="tag">&lt;/<span class="name">label</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">id</span>=<span class="string">"john"</span> <span class="attr">value</span>=<span class="string">"John"</span> <span class="attr">v-model</span>=<span class="string">"checkedNames"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">label</span> <span class="attr">for</span>=<span class="string">"john"</span>&gt;</span>John<span class="tag">&lt;/<span class="name">label</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">id</span>=<span class="string">"mike"</span> <span class="attr">value</span>=<span class="string">"Mike"</span> <span class="attr">v-model</span>=<span class="string">"checkedN</span></span></span><br><span class="line"><span class="tag"><span class="string">ames"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">label</span> <span class="attr">for</span>=<span class="string">"mike"</span>&gt;</span>Mike<span class="tag">&lt;/<span class="name">label</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span>&gt;</span>Checked names: &#123;&#123; checkedNames &#125;&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">new</span> Vue(&#123; <span class="attr">el</span>: <span class="string">'...'</span>, <span class="attr">data</span>: &#123; <span class="attr">checkedNames</span>: [] &#125;&#125;)</span><br></pre></td></tr></table></figure>
<h2 id="十、组件"><a href="#十、组件" class="headerlink" title="十、组件"></a>十、组件</h2><h3 id="什么是组件？"><a href="#什么是组件？" class="headerlink" title="什么是组件？"></a>什么是组件？</h3><ul>
<li>组件（Component）是 <code>Vue.js</code> 最强大的功能之一。组件可以扩展<code>HTML</code>元素，封装可重用的代码。在较高层面上，组件是自定义元素，<code>Vue.js</code> 的编译器为它添加特殊功能。在有些情况下，组件也可以是原生 <code>HTML</code> 元<br>素的形式，以<code>is</code> 特性扩展</li>
</ul>
<h3 id="使用组件"><a href="#使用组件" class="headerlink" title="使用组件"></a>使用组件</h3><p><strong>注册</strong></p>
<ul>
<li>之前说过，我们可以通过以下方式创建一个 <code>Vue</code>实例</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">new</span> Vue(&#123; <span class="attr">el</span>: <span class="string">'#some-element'</span>, <span class="comment">// 选项&#125;)</span></span><br></pre></td></tr></table></figure>
<ul>
<li><p>要注册一个全局组件，你可以使用 <code>Vue.component(tagName, options) 。</code>例如：<code>Vue.component(&#39;my-component&#39;, { // 选项})</code></p>
</li>
<li><p>组件在注册之后，便可以在父实例的模块中以自定义元素 <code>&lt;my-component&gt;&lt;/my-component&gt;</code> 的形式使用。要确保在初始化根实例 之前 注册了组件：<code>&lt;div id=&quot;example&quot;&gt; &lt;my-component&gt;&lt;/my-component&gt;&lt;/div&gt;</code></p>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 注册</span></span><br><span class="line">Vue.component(<span class="string">'my-component'</span>, </span><br><span class="line">&#123; <span class="attr">template</span>: <span class="string">'&lt;div&gt;A custom component!&lt;/div&gt;'</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">//创建根实例</span></span><br><span class="line"><span class="keyword">new</span> Vue(&#123; <span class="attr">el</span>: <span class="string">'#example'</span>&#125;)</span><br></pre></td></tr></table></figure>
<ul>
<li>渲染为：<code>&lt;div id=&quot;example&quot;&gt; &lt;div&gt;A custom component!&lt;/div&gt;&lt;/div&gt;</code></li>
</ul>
<p><strong>局部注册</strong></p>
<ul>
<li>不必在全局注册每个组件。通过使用组件实例选项注册，可以使组件仅在另一个实例/组件的作用域中可用</li>
</ul>
<p><strong>构成组件</strong></p>
<ul>
<li>组件意味着协同工作，通常父子组件会是这样的关系：组件 A 在它的模版中使用了组件 B 。它们之间必然需要相互通信：父组件要给子组件传递数据，子组件需要将它内部发生的事情告知给父组件。然而，在一个良<br>好定义的接口中尽可能将父子组件解耦是很重要的。这保证了每个组件可以在相对隔离的环境中书写和理解，也大幅提高了组件的可维护性和可重用性</li>
<li>在 <code>Vue.js</code>中，父子组件的关系可以总结为 <code>props down</code>, <code>events up</code> 。父组件通过 <code>props</code> 向下传递数据给子组件，子组件通过 <code>events</code>给父组件发送消息。看看它们是怎么工作的</li>
</ul>
<p><img src="./images/1489926033814.jpg" alt="enter description here" title="1489926033814"></p>
<h3 id="Props"><a href="#Props" class="headerlink" title="Props"></a>Props</h3><p><strong>使用Props传递数据</strong></p>
<ul>
<li>组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用<code>props</code>把数据传给子组件。</li>
<li><code>prop</code>是父组件用来传递数据的一个自定义属性。子组件需要显式地用 <code>props</code> 选项 声明 <code>“prop”：</code></li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">Vue.component(<span class="string">'child'</span>, &#123; </span><br><span class="line"><span class="comment">// 声明 props</span></span><br><span class="line">props: [<span class="string">'message'</span>],</span><br><span class="line"><span class="comment">// 就像 data 一样，prop 可以用在模板内</span></span><br><span class="line"><span class="comment">// 同样也可以在 vm 实例中像 “this.message” 这样使用</span></span><br><span class="line">template: <span class="string">'&lt;span&gt;&#123;&#123; message&#125;&#125;&lt;/span&gt;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">'</span>&#125;)</span><br></pre></td></tr></table></figure>
<ul>
<li>然后向它传入一个普通字符串<code>&lt;child message=&quot;hello!&quot;&gt;&lt;/child&gt;</code></li>
<li>结果：hello!</li>
</ul>
<p><strong>动态 Props</strong></p>
<ul>
<li>类似于用<code>v-bind</code> 绑定 <code>HTML</code> 特性到一个表达式，也可以用 <code>v-bind</code> 绑定动态 <code>props</code>到父组件的数据。每当父组件的数据变化时，也会传导给子组件：</li>
</ul>
<p><strong>单向数据流</strong></p>
<ul>
<li><code>prop</code>是单向绑定的：当父组件的属性变化时，将传导给子组件，但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解</li>
<li>另外，每次父组件更新时，子组件的所有 <code>prop</code>都会更新为最新值。这意味着你不应该在子组件内部改变<code>prop</code> 。如果你这么做了，<code>Vue</code> 会在控制台给出警告</li>
</ul>
<h2 id="十一、附录"><a href="#十一、附录" class="headerlink" title="十一、附录"></a>十一、附录</h2><h3 id="附录一-MVC、MVP、MVVM模式对比"><a href="#附录一-MVC、MVP、MVVM模式对比" class="headerlink" title="附录一 MVC、MVP、MVVM模式对比"></a>附录一 MVC、MVP、MVVM模式对比</h3><h4 id="MVC"><a href="#MVC" class="headerlink" title="MVC"></a>MVC</h4><hr>
<h5 id="什么是MVC"><a href="#什么是MVC" class="headerlink" title="什么是MVC"></a>什么是MVC</h5><hr>
<ul>
<li>MVC是一种模式，它将应用分为3个部分：数据（模型）、表现层（视图）、用户交互层（控制器）</li>
<li>一个事件的处理大概是这样<ul>
<li>用户和应用产生交互</li>
<li>控制器的事件处理器被触发</li>
<li>控制器从模型中请求数据，并将其交给视图</li>
<li>视图将数据呈现给用户</li>
</ul>
</li>
</ul>
<h5 id="模型（数据保存）"><a href="#模型（数据保存）" class="headerlink" title="模型（数据保存）"></a>模型（数据保存）</h5><hr>
<ul>
<li>模型用来存放用户的所有数据对象。比如有一个user模型，用来存放用户列表、他们的属性以及所有和模型有关的逻辑</li>
<li>模型不必知晓视图和控制器的细节，模型只需包含数据以及直接和这些数据相关的逻辑</li>
</ul>
<h5 id="视图（用户界面）"><a href="#视图（用户界面）" class="headerlink" title="视图（用户界面）"></a>视图（用户界面）</h5><hr>
<ul>
<li>视图是呈现给用户的，用户与之产生交互。在JavaScript应用中，视图大都是由HTML、css、JavaScript模板组成的</li>
</ul>
<h5 id="控制器（业务逻辑）"><a href="#控制器（业务逻辑）" class="headerlink" title="控制器（业务逻辑）"></a>控制器（业务逻辑）</h5><hr>
<ul>
<li>控制器是模型和视图之间的纽带。控制器从视图获得事件和输入，对它们进行进行处理，并相应的更新视图。</li>
<li>当页面加载时，控制器会给视图添加事件监听，比如监听表单提交或按钮点击。然后当用户和你的应用产生交互时，控制器中的事件触发器就开始工作了</li>
</ul>
<h5 id="总结一下："><a href="#总结一下：" class="headerlink" title="总结一下："></a>总结一下：</h5><hr>
<ul>
<li><code>Controller</code> 监听 <code>Model</code> 变化，<code>Model</code> 一变，<code>Controller</code> 就会去更新<code>View</code>。</li>
<li><p><code>Controller</code> 监听用户交互，用户点了提交或修改按钮，Controller 就要去更新 Model</p>
</li>
<li><p><code>View</code> 传送指令到 <code>Controller</code></p>
</li>
<li><code>Controller</code> 完成业务逻辑后，要求 <code>Model</code> 改变状态</li>
<li><code>Model</code> 将新的数据发送到 <code>View</code>，用户得到反馈</li>
</ul>
<p>各部分之间的通信方式</p>
<p><img src="http://image.beekka.com/blog/2015/bg2015020105.png" alt></p>
<h4 id="互动模式"><a href="#互动模式" class="headerlink" title="互动模式"></a>互动模式</h4><hr>
<ul>
<li>接受用户指令时，MVC 可以分成两种方式。一种是通过 View 接受指令，传递给 Controller</li>
</ul>
<p><img src="http://image.beekka.com/blog/2015/bg2015020106.png" alt></p>
<ul>
<li>另一种是直接通过controller接受指令</li>
</ul>
<p><img src="http://image.beekka.com/blog/2015/bg2015020107.png" alt></p>
<h4 id="MVP"><a href="#MVP" class="headerlink" title="MVP"></a>MVP</h4><hr>
<ul>
<li><code>MVP</code> 模式将 <code>Controller 改名为</code>Presenter`，同时改变了通信方向</li>
</ul>
<p><img src="http://image.beekka.com/blog/2015/bg2015020109.png" alt></p>
<ul>
<li>各部分之间的通信，都是双向的。</li>
<li><code>View</code> 与<code>Model</code> 不发生联系，都通过 <code>Presenter</code> 传递。</li>
<li><code>View</code> 非常薄，不部署任何业务逻辑，称为”被动视图”（Passive View），即没有任何主动性，而 Presenter非常厚，所有逻辑都部署在那里</li>
</ul>
<h4 id="MVVM"><a href="#MVVM" class="headerlink" title="MVVM"></a>MVVM</h4><hr>
<ul>
<li><code>MVVM</code> 模式将 <code>Presenter</code> 改名为 <code>ViewModel</code>，基本上与 <code>MVP</code> 模式完全一致</li>
<li>唯一的区别是，它采用双向绑定（data-binding）：<code>View</code>的变动，自动反映在 <code>ViewModel</code>，反之亦然</li>
</ul>
<p><img src="http://image.beekka.com/blog/2015/bg2015020110.png" alt></p>
<h3 id="附录二-vue与其他框架的对比"><a href="#附录二-vue与其他框架的对比" class="headerlink" title="附录二 vue与其他框架的对比"></a>附录二 vue与其他框架的对比</h3><h4 id="React"><a href="#React" class="headerlink" title="React"></a>React</h4><ul>
<li><code>React</code> 和 <code>Vue</code> 有许多相似之处，它们都有<ul>
<li>使用 <code>Virtual DOM</code></li>
<li>提供了响应式（Reactive）和组件化（Composable）的视图组件。</li>
<li>将注意力集中保持在核心库，伴随于此，有配套的路由和负责处理全局状态管理的库</li>
</ul>
</li>
</ul>
<h4 id="angular1"><a href="#angular1" class="headerlink" title="angular1"></a>angular1</h4><ul>
<li><code>Vue</code> 的一些语法和 <code>Angular</code>的很相似（例如 <code>v-if vs ng-if</code>）。因为<code>Angular</code>是 <code>Vue</code>早期开发的灵感来源。然而，Angular 中存在的许多问题，在 Vue 中已经得到解决</li>
</ul>
<p><strong>复杂性</strong></p>
<ul>
<li>在 <code>API</code> 与设计两方面上<code>Vue.js</code>都比 <code>Angular 1</code> 简单得多，因此你可以快速地掌握它的全部特性并投入开发。</li>
</ul>
<p><strong>灵活性和模块化</strong></p>
<ul>
<li><code>Vue.js</code> 是一个更加灵活开放的解决方案。它允许你以希望的方式组织应用程序，而不是在任何时候都必须遵循 <code>Angular 1</code>制定的规则，这让<code>Vue</code>能适用于各种项目。我们知道把决定权交给你是非常必要的</li>
</ul>
<p><strong>数据绑定</strong></p>
<ul>
<li><code>Angular 1</code>使用双向绑定，<code>Vue</code> 在不同组件间强制使用单向数据流。这使应用中的数据流更加清晰易懂。</li>
</ul>
<p><strong>指令与组件</strong></p>
<ul>
<li>在 <code>Vue</code> 中指令和组件分得更清晰。指令只封装 <code>DOM</code> 操作，而组件代表一个自给自足的独立单元 —— 有自己的视图和数据逻辑。在 <code>Angular</code> 中两者有不少相混的地方</li>
</ul>
<p><strong>性能</strong></p>
<ul>
<li><code>Vue</code> 有更好的性能，并且非常非常容易优化，因为它不使用脏检查</li>
<li>在 <code>Angular 1</code> 中，当 <code>watchers</code> 越来越多时会变得越来越慢，因为作用域内的每一次变化，所有 <code>watchers</code>都要重新计算。并且，如果一些<code>watchers</code>触发另一个更新，脏检查循环（digest cycle）可能要运行多次。Angular 用户常常要使用深奥的技术，以解决脏检查循环的问题。有时没有简单的办法来优化有大量 <code>watchers</code>的作用域</li>
<li><code>Vue</code> 则根本没有这个问题，因为它使用基于依赖追踪的观察系统并且异步队列更新，所有的数据变化都是独立触发，除非它们之间有明确的依赖关系</li>
</ul>

      </div>
    
  </div>

</article>

<button class="assist-btn2 circle" id="assist_btn2" title="点亮屏幕" style="left: 27px; top: 152px;">
  <i class="iconfont" style="display:inline-block;color:red;width:20px;height:20px;">&#xe61d;</i>
</button>
<button class="assist-btn1 circle" id="assist_btn1" title="关闭屏幕亮度" style="left: 27px; top: 152px;">
  <i class="iconfont toc-title" style="display:inline-block;color:red;width:20px;height:20px;">&#xe61d;</i>
</button>


<script src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>	

<script src="https://my.openwrite.cn/js/readmore.js" type="text/javascript"></script>
<script>
  const btw = new BTWPlugin();
  btw.init({
    id: "container",
    blogId: "22699-1592137983091-414",
    name: "前端进阶之旅",
    qrcode: "https://poetries1.gitee.io/img-repo/2020/06/qrcode.jpg",
    keyword: "3a3b3c",
  });
</script>

<script type="text/javascript">

// white theme
var body = {color: "#555", background: "#000"};
var a_tag = {color: "#222"};
var header = { background: "#222"};
var logo_line_i = {background: "#222"};
// var post_code = {background: "#eee", color: "#222"};

function switch_theme() {
 $("body").css(body);
 $("a:not('.links-of-author-item a, .site-state-item a, .site-state-posts a, .feed-link a, .motion-element a, .post-tags a, .show-commit-cls a, #donate_board a')").css(a_tag);
 $(".header, .footer").css(header);
 $(".logo-line-before i, .logo-line-after i").css(logo_line_i);
 //$(".post code").css(post_code);
 $("#idhyt-surprise-ball #idhyt-surprise-ball-animation .drag").css(a_tag);
 $(".post-title-link, .posts-expand .post-meta, .post-comments-count, .disqus-comment-count, .post-category a, .post-nav-next a, .post-nav-item a").css(a_tag);
 
 // $("code").css({color: '#c5c8c6', background: '#1d1f21'});
 //$("#assist_btn1").hide(1500);
}

$(function () {
$("#assist_btn2").css("display","none");
 $("#assist_btn1").click(function() {
     switch_theme();
$("div#toc.toc-article").css({
 "background":"#eaeaea",
 "opacity":1
});
$(".toc-article ol").show();
$("#toc.toc-article .toc-title").css("color","#a98602");
$("#assist_btn1").css("display","none");
$("#assist_btn2").css("display","block");
 });
$("#assist_btn2").click(function() {
$("#assist_btn2").css("display","none");
$("#assist_btn1").css("display","block");
$("body").css("background","url(http://www.miaov.com/static/ie/images/news/bg.png)")
     $(".header, .footer").css("background","url(http://www.miaov.com/static/ie/images/news/bg.png)")
$(".toc-article ol").toggle(1000);
 });
});


//背景随机

var Y, O, E, L, B, C, T, z, N, S, A, I;
!function() {
var e = function() {
for (O.clearRect(0, 0, L, B), T = [{
x: 0,
y: .7 * B + C
}, {
x: 0,
y: .7 * B - C
}]; T[1].x < L + C;) t(T[0], T[1])
}, t = function(e, t) {
O.beginPath(), O.moveTo(e.x, e.y), O.lineTo(t.x, t.y);
var n = t.x + (2 * I() - .25) * C,
 r = a(t.y);
O.lineTo(n, r), O.closePath(), N -= S / -50, O.fillStyle = "#" + (127 * A(N) + 128 << 16 | 127 * A(N + S / 3) + 128 << 8 | 127 * A(N + S / 3 * 2) + 128).toString(16), O.fill(), T[0] = T[1], T[1] = {
 x: n,
 y: r
}
}, a = function n(e) {
var t = e + (2 * I() - 1.1) * C;
return t > B || t < 0 ? n(e) : t
};
Y = document.getElementById("evanyou"), O = Y.getContext("2d"), E = window.devicePixelRatio || 1, L = window.innerWidth, B = window.innerHeight, C = 90, z = Math, N = 0, S = 2 * z.PI, A = z.cos, I = z.random, Y.width = L * E, Y.height = B * E, O.scale(E, E), O.globalAlpha = .6, document.onclick = e, document.ontouchstart = e, e()
}()

   
$("#toc-eye").click(function(){
$("#toc.toc-article").toggle(1000);
});

</script>


   
  <div class="text-center donation">
    <div class="inner-donation">
      <span class="btn-donation">支持一下</span>
      <div class="donation-body">
        <div class="tip text-center">扫一扫，支持poetries</div>
        <ul>
        
          <li class="item">
            
              <span>微信扫一扫</span>
            
            <img src="/images/weixin.jpg" alt="">
          </li>
        
          <li class="item">
            
              <span>支付宝扫一扫</span>
            
            <img src="/images/zhifubao.jpg" alt="">
          </li>
        
        </ul>
      </div>
    </div>
  </div>


   
  <div class="box-prev-next clearfix">
    <a class="show pull-left" href="/2017/03/12/front-end-interview-summary/">
        <i class="icon icon-angle-left"></i>
    </a>
    <a class="show pull-right" href="/2017/03/22/closure-summary/">
        <i class="icon icon-angle-right"></i>
    </a>
  </div>




</div>


  <a id="backTop" class="back-top">
    <i class="icon-angle-up"></i>
  </a>




  <div class="modal" id="modal">
  <span id="cover" class="cover hide"></span>
  <div id="modal-dialog" class="modal-dialog hide-dialog">
    <div class="modal-header">
      <span id="close" class="btn-close">关闭</span>
    </div>
    <hr>
    <div class="modal-body">
      <ul class="list-toolbox">
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/archives/"
              rel="noopener noreferrer"
              target="_self"
              >
              博客
            </a>
          </li>
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/categories/"
              rel="noopener noreferrer"
              target="_self"
              >
              分类
            </a>
          </li>
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/tags/"
              rel="noopener noreferrer"
              target="_self"
              >
              标签
            </a>
          </li>
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/search/"
              rel="noopener noreferrer"
              target="_self"
              >
              搜索
            </a>
          </li>
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/link/"
              rel="noopener noreferrer"
              target="_self"
              >
              友链
            </a>
          </li>
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/about/"
              rel="noopener noreferrer"
              target="_self"
              >
              关于
            </a>
          </li>
        
      </ul>

    </div>
  </div>
</div>



  
      <div class="fexo-comments comments-post">
    

    

    
    

    

    
    

    

<!-- Gitalk评论插件通用代码 -->
<div id="gitalk-container"></div>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css">
<script src="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script>
<script>
const gitalk = new Gitalk({
  clientID: '5567a2c4abb858009d96',
  clientSecret: 'b9039ec056cf5c2346b3cdb63308a28c163f91e5',
  repo: 'poetries.github.io',
  owner: 'poetries',
  // 在这里设置一下截取前50个字符串, 这是因为 github 对 label 的长度有了要求, 如果超过
  // 50个字符串则会报错.
  // id: location.pathname.split('/').pop().substring(0, 49),
  id: location.pathname,
  admin: ['poetries'],
  // facebook-like distraction free mode
  distractionFreeMode: false
})
gitalk.render('gitalk-container')
</script>
<!-- Gitalk代码结束 -->



  </div>

  

  <script type="text/javascript">
  function loadScript(url, callback) {
    var script = document.createElement('script')
    script.type = 'text/javascript';

    if (script.readyState) { //IE
      script.onreadystatechange = function() {
        if (script.readyState == 'loaded' ||
          script.readyState == 'complete') {
          script.onreadystatechange = null;
          callback();
        }
      };
    } else { //Others
      script.onload = function() {
        callback();
      };
    }

    script.src = url;
    document.getElementsByTagName('head')[0].appendChild(script);
  }

  window.onload = function() {
    loadScript('/js/bundle.js?235683', function() {
      // load success
    });
  }
</script>


  <!-- 页面点击小红心 -->
  <script type="text/javascript" src="/js/clicklove.js"></script>
 
  
</body>
</html>
